#include<iostream>
#include<pthread.h>
#include<queue>
#include<unistd.h>
#include"Mutex.hpp"
#include"Cond.hpp"
using namespace std;
using namespace LockModule;
using namespace CondModule;
//v1
// namespace BlockQueueModule{
//     static int gcap=10;
//     template<typename T>
//     class BlockQueue{
//         private:
//         bool IsFull(){
//             return _q.size()==_cap;
//         }
//         bool IsEmpty(){
//             return _q.size()==0;
//         }
//     public:
//     void Equeue(const T& in)//入队列
//     {
//         pthread_mutex_lock(&_mutex);
//         while(IsFull())
//         {
//             cout<<"生产者等待"<<endl;
//             _pwait_num++;
//             pthread_cond_wait(&_product_cond,&_mutex);//判断IsFull是临界资源且非原子性，所以这一步必须在加锁后进行
//         _pwait_num--;
//         cout<<"生产者醒来"<<endl;
//         }
//         _q.push(in);
//         if(_cwait_num)
//         {
//             cout<<"叫醒消费者"<<endl;
//             pthread_cond_signal(&_consumer_cond);
//         }
//         pthread_mutex_unlock(&_mutex);
// }
// void Pop(T*out)
// {
//     pthread_mutex_lock(&_mutex);
//     while(IsEmpty())
//     {
//         cout<<"消费者等待"<<endl;
//         _cwait_num++;
//         pthread_cond_wait(&_consumer_cond,&_mutex);
//         _cwait_num--;
//         cout<<"消费者醒来"<<endl;
//     }
//     *out=_q.front();
//     _q.pop();
//     if(_pwait_num)
//     {
//         cout<<"叫醒生产者"<<endl;
//         pthread_cond_signal(&_product_cond);
//     }
//     pthread_mutex_unlock(&_mutex);
// }
//     BlockQueue(int cap=gcap)
//     :_cap(cap)
//     ,_cwait_num(0)
//     ,_pwait_num(0)
//     {
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_consumer_cond,nullptr);
//         pthread_cond_init(&_product_cond,nullptr);
//     }
//     ~BlockQueue()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_consumer_cond);
//         pthread_cond_destroy(&_product_cond);
//     }

//     private:
//     std::queue<T>_q;//保存数据的容器
//     int _cap;//队列最大容量
//     pthread_mutex_t _mutex;
//     pthread_cond_t _product_cond;
//     pthread_cond_t _consumer_cond;
//     int _cwait_num;
//     int _pwait_num;
//     };
// }

//v2
namespace BlockQueueModule{
    static int gcap=10;
    template<typename T>
    class BlockQueue{
        private:
        bool IsFull(){
            return _q.size()==_cap;
        }
        bool IsEmpty(){
            return _q.size()==0;
        }
    public:
    void Equeue(const T& in)//入队列
    {
        LockGuard lockguard(_mutex);
        while(IsFull())
        {
            cout<<"生产者等待"<<endl;
            _pwait_num++;
           _product_cond.Wait(_mutex);//判断IsFull是临界资源且非原子性，所以这一步必须在加锁后进行
        _pwait_num--;
        cout<<"生产者醒来"<<endl;
        }
        _q.push(in);
        if(_cwait_num)
        {
            cout<<"叫醒消费者"<<endl;
            _consumer_cond.Notify();
        }
}
void Pop(T*out)
{
    LockGuard lockguard(_mutex);
    while(IsEmpty())
    {
        cout<<"消费者等待"<<endl;
        _cwait_num++;
        _consumer_cond.Wait(_mutex);
        _cwait_num--;
        cout<<"消费者醒来"<<endl;
    }
    *out=_q.front();
    _q.pop();
    if(_pwait_num)
    {
        cout<<"叫醒生产者"<<endl;
        _product_cond.Notify();
    }
}
    BlockQueue(int cap=gcap)
    :_cap(cap)
    ,_cwait_num(0)
    ,_pwait_num(0)
    {}
    ~BlockQueue(){;}

    private:
    std::queue<T>_q;//保存数据的容器
    int _cap;//队列最大容量
    Mutex _mutex;
    Cond _product_cond;
    Cond _consumer_cond;
    int _cwait_num;
    int _pwait_num;
    };
}